104. シーンの構築: 2.パーティクルのランダム配置

擬似乱数関数を使用して、パーティクルを球面上に分散させる方法を学びます。

p5.js 2.0 WebGL p5.strands Shader GLSL
Learning Tutorial

パーティクルを球面上に配置する

先ほどは X 軸に沿って並べましたが、今度はパーティクルを球面上にランダムに配置して、より興味深いパターンを作ってみましょう。

スケッチのソースコードを見てみましょう:

let instancingShader;
let instancingStrokeShader;
let particleModel;

function instancingCallback() {
  // 擬似乱数関数 (出典: https://stackoverflow.com/questions/4200224/random-noise-functions-for-glsl)
  function rand(seed) {
    return fract(sin(dot(seed, [12.9898, 78.233])) * 43758.5453123);
  }

  function randomPositionOnSphere() {
    let id = instanceID();
    let theta = rand([id, 0.1234]) * TWO_PI;
    let phi = rand([id, 3.321]) * PI;

    let r = 180;
    let x = r * sin(phi) * cos(theta);
    let y = r * cos(phi);
    let z = r * sin(phi) * sin(theta);
    return [x, y, z];
  }

  getWorldInputs((inputs) => {
    inputs.position += randomPositionOnSphere();
    return inputs;
  });
}

async function setup() {
  createCanvas(400, 400, WEBGL);
  pixelDensity(1);
  particleModel = buildGeometry(() => sphere(10, 4, 2));
  instancingShader = baseColorShader().modify(instancingCallback);
  instancingStrokeShader = baseStrokeShader().modify(instancingCallback);
}

function draw() {
  background(0);
  orbitControl();
  shader(instancingShader);
  fill(255, 100, 150);
  strokeShader(instancingStrokeShader);
  model(particleModel, 1000);
}

ここで使用している rand() ヘルパー関数は、p5.strands に移植された 3 つの GLSL 関数を使用しています:

function rand(seed) {
  return fract(sin(dot(seed, [12.9898, 78.233])) * 43758.5453123);
}
  • fract(): 数値の小数部分を取り出します(例:3.420.42
  • sin(): 角度のサイン(正弦)を返します
  • dot(): 2 つのベクトルのドット積(内積)を返します。これはベクトルの類似度を測るものです。

これらの関数は、本来の数学的な意味を持ちつつ、ここではインスタンス ID に基づいて擬似乱数(決まった入力に対してランダムに見える値を返す)を生成するために組み合わされています。

シェーダー内でランダム性が必要な場合、通常の random() 関数は使えないため、このような数学的な手法が一般的に使われます。

License

Original URL: https://beta.p5js.org/tutorials/intro-to-p5-strands/

License: MIT License

Copyright (c) 2015-present p5.js contributors & The Processing Foundation